package com.ruoyi.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.razorpay.RazorpayClient;
import com.razorpay.RazorpayException;
import com.ruoyi.common.config.datasource.DynamicDataSourceContextHolder;
import com.ruoyi.common.enums.LiveStatus;
import com.ruoyi.common.enums.OrderStatus;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.CodeUtils;
import com.ruoyi.common.utils.LogUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.exception.AjaxException;
import com.ruoyi.system.domain.SysChannel;
import com.ruoyi.system.domain.SysIndiaMessage;
import com.ruoyi.system.domain.SysOrder;
import com.ruoyi.system.mapper.SysChannelMapper;
import com.ruoyi.system.mapper.SysIndiaMessageMapper;
import com.ruoyi.system.mapper.SysOrderMapper;
import com.ruoyi.system.service.ISysPayService;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @author Ericcc
 * @version v0.01
 * @date 2021/3/25
 */
@Service
public class SysPayServiceImpl implements ISysPayService {

    @Autowired
    private SysOrderMapper sysOrderMapper;

    @Autowired
    private SysChannelMapper sysChannelMapper;

    @Autowired
    private SysIndiaMessageMapper sysIndiaMessageMapper;

    @Override
    public String getLink(long orderid) throws Exception {
        SysOrder sysOrder = sysOrderMapper.selectSysOrderById(orderid);
        if (sysOrder==null){
            throw new AjaxException("error,please try again");
        }
        if (sysOrder.getStatus()== OrderStatus.OK.getCode()){
            throw new AjaxException("this order is complete");
        }
        SysChannel sysChannel = sysChannelMapper.selectSysChannelById(sysOrder.getChannelId());
        if (sysChannel==null){
            throw new BusinessException("channel's error");
        }
        if (sysChannel.getStatus()== LiveStatus.DISABLE.getCode()){
            throw new BusinessException("channel forbbiden");
        }
        String data = null;
        //Razorpay
        if (sysChannel.getChannelGateway().contains("razorpay")){
            data = razorpay(sysOrder,sysChannel);
        }
        //cashfree
        if (sysChannel.getChannelGateway().contains("cashfree")){
            data = cashfree(sysOrder,sysChannel);
        }
        return data;
    }

    private String cashfree(SysOrder sysOrder, SysChannel sysChannel) throws NoSuchAlgorithmException, InvalidKeyException {
        Random random = new Random();
        int num = random.nextInt(6000) + 1;
        SysIndiaMessage sysIndiaMessage = sysIndiaMessageMapper.selectSysIndiaMessageById(Long.valueOf(num));
        String name = sysIndiaMessage.getNames();
        String email = sysIndiaMessage.getEmail();
        String mobile = sysIndiaMessage.getMobile();


        Map<String, String> postData = new HashMap<>();
        postData.put("appId", sysChannel.getChannelAppid());
        if (sysOrder.getPayLink()!=null){
            sysOrder.setOrderCode(String.valueOf(CodeUtils.getCode()));
            postData.put("orderId", sysOrder.getOrderCode());
        }else {
            postData.put("orderId", sysOrder.getOrderCode());
        }
        postData.put("orderAmount", sysOrder.getOrderAmount().setScale(0, BigDecimal.ROUND_DOWN).toString());
        postData.put("orderCurrency", "INR");
        postData.put("orderNote", "pay");
        postData.put("customerName", name);
        postData.put("customerEmail", email);
        postData.put("customerPhone", mobile);
        postData.put("returnUrl", sysOrder.getCallbackUrl());
        postData.put("notifyUrl", sysChannel.getChannelNotifyurl());
        String data = "";
        SortedSet<String> keys = new TreeSet<>(postData.keySet());
        for (String key : keys) {
            data = data + key + postData.get(key);
        }
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key_spec = new
                SecretKeySpec(sysChannel.getChannelKey().getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key_spec);
        String signature = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(data.getBytes()));

        // 报文签名
        StringBuilder sb = new StringBuilder();
        sb.append("<form hidden=\"hidden\" id=\"redirectForm\" action=\"https://www.cashfree.com/checkout/post/submit\" method=\"post\">");
        sb.append("<p><input type=\"hidden\" name=\"appId\" value=\"" + postData.get("appId") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"orderId\" value=\"" + postData.get("orderId") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"orderAmount\" value=\"" + postData.get("orderAmount") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"orderCurrency\" value=\"" + postData.get("orderCurrency") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"orderNote\" value=\"" + postData.get("orderNote") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"customerName\" value=\"" + postData.get("customerName") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"customerEmail\" value=\"" + postData.get("customerEmail") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"customerPhone\" value=\"" + postData.get("customerPhone") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"returnUrl\" value=\"" + postData.get("returnUrl") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"notifyUrl\" value=\"" + postData.get("notifyUrl") + "\"></p>");
        sb.append("<p><input type=\"hidden\" name=\"signature\" value=\"" + signature + "\"></p>");
        sb.append("<p></form>");
        sb.append("<script>document.getElementById('redirectForm').submit();</script>");
        LogUtils.log.info("sb == {}", sb);

        sysOrder.setPayLink("1");
        if (sysOrderMapper.updateSysOrder(sysOrder) != 1) {
            throw new BusinessException("order error");
        }
        return sb.toString();
    }

    private String razorpay(SysOrder sysOrder,SysChannel sysChannel) {
        long time = System.currentTimeMillis();
        JSONObject jsonObject;
        sysOrder.setPayLink("1");   //测试用的 之后删除
        if (StringUtils.isBlank(sysOrder.getPayLink())){
            com.razorpay.Order razorpayOrder;
            try {
                RazorpayClient razorpay = new RazorpayClient(sysChannel.getChannelAppid(),sysChannel.getChannelKey());
                org.json.JSONObject orderRequest = new org.json.JSONObject();
                orderRequest.put("amount", sysOrder.getOrderAmount().setScale(0, BigDecimal.ROUND_DOWN).multiply(BigDecimal.valueOf(100)).toString()); // amount in the smallest currency unit
                orderRequest.put("currency", "INR");
                orderRequest.put("receipt", sysOrder.getOrderCode());
                razorpayOrder = razorpay.Orders.create(orderRequest);
            } catch (RazorpayException | JSONException e) {
                LogUtils.log.info("错误是 == {}", e.getMessage());
                throw new BusinessException("razorpay error");
            }

            if (razorpayOrder == null) {
                throw new BusinessException("razorpay error");
            }

            jsonObject = new JSONObject();
            jsonObject.put("key", sysChannel.getChannelAppid());
            jsonObject.put("amount", razorpayOrder.get("amount"));
            jsonObject.put("currency", razorpayOrder.get("currency"));
            jsonObject.put("name", "test");
            jsonObject.put("image", "https://ask.mixyd.com/img/logo.jpg");
            jsonObject.put("order_id", razorpayOrder.get("id"));
            jsonObject.put("callback_url", sysOrder.getCallbackUrl());
            JSONObject prefill = new JSONObject();
            prefill.put("name", "test");
            prefill.put("email", "test");
            prefill.put("contact", "test");
//            if (RazorpayMethodEnum.CARD.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.CARD.getMessage());
//            } else if (RazorpayMethodEnum.NETBANKING.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.NETBANKING.getMessage());
//            } else if (RazorpayMethodEnum.WALLET.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.WALLET.getMessage());
//            } else if (RazorpayMethodEnum.EMI.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.EMI.getMessage());
//            } else if (RazorpayMethodEnum.UPI.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.UPI.getMessage());
//            }
            jsonObject.put("prefill", prefill);
            JSONObject notes = new JSONObject();
            notes.put("address", "Razorpay Corporate Office");
            jsonObject.put("notes", notes);
            JSONObject theme = new JSONObject();
            theme.put("color", "#3399cc");
            jsonObject.put("theme", theme);

            sysOrder.setPayLink("1");
            sysOrder.setOrderCode(sysOrder.getOrderCode());
            sysOrder.setOrderChannelCode(razorpayOrder.get("id"));
            if (sysOrderMapper.updateSysOrder(sysOrder) != 1) {
                throw new AjaxException("system error;please try again");
            }
            LogUtils.log.info("razorpay请求的数据 == {}",jsonObject.toString());
            LogUtils.log.info("支付下单执行毫秒数 == {}", System.currentTimeMillis() - time);
        } else {
            jsonObject = new JSONObject();
            jsonObject.put("key", sysChannel.getChannelAppid());
            jsonObject.put("amount", sysOrder.getOrderAmount().setScale(0, BigDecimal.ROUND_DOWN).multiply(BigDecimal.valueOf(100)).toString());
            jsonObject.put("currency", "INR");
            jsonObject.put("name", "test");
            jsonObject.put("image", "https://ask.mixyd.com/img/logo.jpg");
            jsonObject.put("order_id", sysOrder.getOrderCode());
            jsonObject.put("callback_url", sysOrder.getCallbackUrl());
            JSONObject prefill = new JSONObject();
            prefill.put("name", "test");
            prefill.put("email", "test");
            prefill.put("contact", "test");
//            if (RazorpayMethodEnum.CARD.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.CARD.getMessage());
//            } else if (RazorpayMethodEnum.NETBANKING.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.NETBANKING.getMessage());
//            } else if (RazorpayMethodEnum.WALLET.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.WALLET.getMessage());
//            } else if (RazorpayMethodEnum.EMI.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.EMI.getMessage());
//            } else if (RazorpayMethodEnum.UPI.getCode() == methods){
//                prefill.put("method", RazorpayMethodEnum.UPI.getMessage());
//            }
            jsonObject.put("prefill", prefill);
            JSONObject notes = new JSONObject();
            notes.put("address", "Razorpay Corporate Office");
            jsonObject.put("notes", notes);
            JSONObject theme = new JSONObject();
            theme.put("color", "#3399cc");
            jsonObject.put("theme", theme);

            sysOrder.setPayLink("1");
            if (sysOrderMapper.updateSysOrder(sysOrder) != 1) {
                throw new BusinessException("system error;please try again");
            }
            LogUtils.log.info("razorpay请求的数据 == {}",jsonObject.toString());
        }

        return jsonObject.toString();
    }
}
